package cz.vargagab.repo;

import java.util.List;
import java.util.Queue;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cz.vargagab.domain.ClientRmiNode;
import cz.vargagab.domain.LogObject;
import cz.vargagab.domain.Request;
import cz.vargagab.domain.Response;
import cz.vargagab.domain.ServerRmiNode;

public class ExternalClientServiceImpl implements ExternalClientService {

	@Autowired
	InternalClientService internalClientService;
	
	/**
	 * Server posiela info o sebe klientovi cez klientov RMI interface
	 */
	public void updateServer (ServerRmiNode server){
		internalClientService.setServerNode(server);
	}
	
	public ServerRmiNode getServer(){
		return internalClientService.getServerNode();
	}

	/**
	 * Server posiela pri logoute info o tom, ze uz serverNode nema mat nastaveny
	 */
	@Override
	public void dc() {
		internalClientService.setServerNode(null);
	}

	/**
	 * Testovacia metoda, ktora sa vola, ak chce niekto vyuzivat RMI rozhranie klienta - len pre otestovanie, ci klient zije
	 */
	@Override
	public void testConnection() {
		System.out.println("Testing connection before calling ExternalClientService" );
	}

	/**
	 * Server posiela zoznam nodov
	 */
	@Override
	public void updateClients(List<ClientRmiNode> clients) {
		internalClientService.getLog().add(new LogObject("Updating clients, current count is " + clients.size() ));
		internalClientService.setClientNodes(clients);
	}
	
	@Override
	public Queue<Request> getQueue(){
		return internalClientService.getQueue();
	}

	/**
	 * KLient mi poslal request. POzrem sa, ci je vo fronte prvy. AK nie je, cakam dokym nebude a odpoved poslem az potom
	 */
	@Override
	public void sendRequest(Request r) throws InterruptedException {
		getQueue().add(r);
		internalClientService.getLog().add(new LogObject("Recieved request from " + r.getRequestingNode().getName() + " with timestamp " +r.getTimestamp()));
		Response response = null;
		//do not send reply until request is the first in the queue
		while(true){
			if ( getQueue().peek().equals(r) ){ //pozrem sa na vrch prioritnej fronty, ale prvok zatial necham tam
				response = new Response(r,Boolean.TRUE,internalClientService.getThisNode());
				break;
			}else{
				Thread.sleep(1000L); // skus znova o 1 sekundu.
			}	
		}
		internalClientService.getLog().add(new LogObject("Sending reply to " + r.getRequestingNode().getName() + " with timestamp " +response.isOk()));
		internalClientService.getClients().get(r.getRequestingNode()).sendReply(response );
	}

	/**
	 * Klient poslal reply na moj request cez RMI. Zalogujem a zapisem do mapy, ze uz mi to prislo
	 */
	@Override
	public void sendReply(Response response) {
		internalClientService.getLog().add(new LogObject("Recieved reply from " + response.getReplyFrom().getName() + " with timestamp " + response.isOk()));
		internalClientService.getReplys().get(response.getRequestTorespondTo()).put(response.getReplyFrom(),response.isOk());
	}

	/**
	 * Klient, ktoreho request mam v prioritnej fronte posiela release - vymazem request zo svojej prioritnej fronty
	 */
	@Override
	public void sendRelease(Request r) {
		internalClientService.getLog().add(new LogObject("Recieved release from " + r.getRequestingNode().getName() ));
		getQueue().remove(r);
	}
	

	//Getters & Setter
	public InternalClientService getInternalClientService() {
		return internalClientService;
	}
	public void setInternalClientService(InternalClientService internalClientService) {
		this.internalClientService = internalClientService;
	}
}
